﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace EOrm
{
    /// <summary>
    /// 数据库服务提供者加载项目
    /// </summary>
    internal class OrmProviderLoader
    {
        /// <summary>
        /// 在当前可执行路径下加载默认数据库服务提供者的路径，默认文件名以Provider.dll结尾
        /// </summary>
        /// <returns>数据库服务提供者的文件路径</returns>
        /// <exception cref="ArgumentException">变量为空错误</exception>
        public static string GetProviderPath()
        {
            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            string[] fileArray = Directory.GetFiles(basePath);
            if (fileArray == null || fileArray.Length <= 0)
            {
                throw new ArgumentException("没有找到对应的数据库服务提供者", "fileArray");
            }
            List<string> files = fileArray.ToList().FindAll(a => a.EndsWith("Provider.dll")).ToList();
            if (files == null || files.Count <= 0)
            {
                throw new ArgumentException("没有找到对应的数据库服务提供者", "fileArray");
            }
            return files[0];
        }
        /// <summary>
        /// 在当前可执行路径下加载数据库服务提供者的路径
        /// </summary>
        /// <param name="providerName">数据库服务提供者的文件名</param>
        /// <returns>数据库服务提供者的文件路径</returns>
        /// <exception cref="ArgumentException">变量为空错误</exception>
        public static string GetProviderPath(string providerName)
        {
            if (providerName == null || string.IsNullOrEmpty(providerName.Trim()))
            {
                throw new ArgumentException("数据库服务提供者的文件名为空", "providerName");
            }
            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            string[] fileArray = Directory.GetFiles(basePath);
            if (fileArray == null || fileArray.Length <= 0)
            {
                throw new ArgumentException("没有找到对应的数据库服务提供者", "fileArray");
            }
            List<string> files = fileArray.ToList().FindAll(a => a.Contains(providerName)).ToList();
            if (files == null || files.Count <= 0)
            {
                throw new ArgumentException("没有找到对应的数据库服务提供者", "fileArray");
            }
            return files[0];
        }
        //================新写法===================//

        /// <summary>
        /// 获取接口
        /// </summary>
        /// <typeparam name="T">接口泛型</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>接口</returns>
        /// <exception cref="Exception">接口未找到异常</exception>
        public static T GetInterface<T>(string dbProviderPath)
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            T result = default(T);
            foreach (Type type in assBly.GetTypes())
            {
                if (type.GetInterface(typeof(T).FullName) != null)
                {
                    result = (T)Activator.CreateInstance(type);
                    if (result != null)
                    {
                        break;
                    }
                }
            }
            if (result == null)
            {
                throw new Exception(string.Format("数据库服务提供者中没有找到对应接口：{0}", typeof(T).Name));
            }
            return result;
        }

        /// <summary>
        /// 获取全部指定接口
        /// </summary>
        /// <typeparam name="T">接口泛型</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>全部接口</returns>
        /// <exception cref="Exception">接口未找到异常</exception>
        public static List<T> GetInterfaces<T>(string dbProviderPath)
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            List<T> result = new List<T>();
            foreach (Type type in assBly.GetTypes())
            {
                if (type.GetInterface(typeof(T).FullName) != null)
                {
                    T tmp = (T)Activator.CreateInstance(type);
                    if (tmp != null)
                    {
                        result.Add(tmp);
                    }
                }
            }
            if (result.Count<=0)
            {
                throw new Exception(string.Format("数据库服务提供者中没有找到对应接口：{0}", typeof(T).Name));
            }
            return result;
        }

        /// <summary>
        /// 获取条件表达式访问器
        /// </summary>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>条件表达式访问器</returns>
        /// <exception cref="Exception">条件表达式访问器未找到异常</exception>
        public static WhereVisitor GetWhereVisitor(string dbProviderPath)
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            WhereVisitor result = null;
            foreach (Type type in assBly.GetTypes())
            {
                if (type.BaseType==typeof(WhereVisitor))
                {
                    result = Activator.CreateInstance(type) as WhereVisitor;
                    if (result != null)
                    {
                        break;
                    }
                }
            }
            if (result == null)
            {
                throw new Exception("数据库服务提供者中没有找到数据服务访问器");
            }
            return result;
        }
        /// <summary>
        /// 获取所有类
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>所有类</returns>
        /// <exception cref="Exception">条件表达式访问器未找到异常</exception>
        public static List<T> GetClasses<T>(string dbProviderPath) where T : class
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            List<T> result = new List<T>();
            foreach (Type type in assBly.GetTypes())
            {
                if (type == typeof(T))
                {
                    T tmp = Activator.CreateInstance(type) as T;
                    if (tmp != null)
                    {
                        result.Add(tmp);
                    }
                }
            }
            if (result.Count<=0)
            {
                throw new Exception("数据库服务提供者中没有找到类");
            }
            return result;
        }
        /// <summary>
        /// 获取类
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>类</returns>
        /// <exception cref="Exception">条件表达式访问器未找到异常</exception>
        public static T GetClass<T>(string dbProviderPath) where T : class
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            T result = null;
            foreach (Type type in assBly.GetTypes())
            {
                if (type == typeof(T))
                {
                    result = Activator.CreateInstance(type) as T;
                    if (result != null)
                    {
                        break;
                    }
                }
            }
            if (result == null)
            {
                throw new Exception("数据库服务提供者中没有找到类");
            }
            return result;
        }
        /// <summary>
        /// 获取所有父类的直接子类
        /// </summary>
        /// <typeparam name="T">父类</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>所有父类的直接子类</returns>
        /// <exception cref="Exception">条件表达式访问器未找到异常</exception>
        public static List<T> GetChildClasses<T>(string dbProviderPath) where T : class
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            List<T> result = new List<T>();
            foreach (Type type in assBly.GetTypes())
            {
                if (type.BaseType == typeof(T))
                {
                    T tmp = Activator.CreateInstance(type) as T;
                    if (tmp != null)
                    {
                        result.Add(tmp);
                    }
                }
            }
            if (result.Count<=0)
            {
                throw new Exception("数据库服务提供者中没有找到父类");
            }
            return result;
        }
        /// <summary>
        /// 获取父类的直接子类
        /// </summary>
        /// <typeparam name="T">父类</typeparam>
        /// <param name="dbProviderPath">数据库服务提供者</param>
        /// <returns>直接子类</returns>
        /// <exception cref="Exception">条件表达式访问器未找到异常</exception>
        public static T GetChildClass<T>(string dbProviderPath) where T : class
        {
            Assembly assBly = Assembly.LoadFrom(dbProviderPath);
            T result = null;
            foreach (Type type in assBly.GetTypes())
            {
                if (type.BaseType == typeof(T))
                {
                    result = Activator.CreateInstance(type) as T;
                    if (result != null)
                    {
                        break;
                    }
                }
            }
            if (result == null)
            {
                throw new Exception("数据库服务提供者中没有找到父类");
            }
            return result;
        }
    }
}
